package com.cjk.controller;

import cn.hutool.poi.excel.ExcelReader;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.alibaba.excel.EasyExcel;
import com.alibaba.fastjson.JSON;
import com.cjk.dto.ExportSensitiveWordDto;
import com.cjk.dto.SensitiveWordDto;
import com.cjk.entity.TbSensitiveWordsExample;
import com.cjk.param.AddSensitiveWordParam;
import com.cjk.param.BaseResult;
import com.cjk.ISensitiveService;
import com.cjk.utils.BaseResultUtils;
import com.cjk.utils.DateUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 敏感词
 */
@RestController
@RequestMapping("/sensitivewords")
@Slf4j
public class SensitiveWordsController {

    /**
     * 导出数据上限1000
     */
    private static final int EXPORT_NUM_LIMIT = 1000;
    /**
     * excel文档后缀
     */
    private static final String EXCEL_SUFFIX = ".xlsx";
    @Autowired
    private ISensitiveService sensitiveService;

    @RequestMapping(value = "/add", method = RequestMethod.POST)
    public BaseResult<Boolean> addWord(@RequestBody AddSensitiveWordParam param) {
        try {
            log.info("增加敏感词-controller-addWord-入参:{}", JSON.toJSONString(param));
            // 参数校验
            checkParam(param);
            SensitiveWordDto sensitiveWordDto = new SensitiveWordDto();
            sensitiveWordDto.setWord(param.getWord());
            sensitiveWordDto.setCategory(param.getCategory());
            // 敏感词落库
            int insert = sensitiveService.insert(sensitiveWordDto);
            log.info("增加敏感词-controller-addWord-出参:{}", insert > 0);
            return BaseResultUtils.generateSuccess(insert > 0);
        } catch (Exception e) {
            log.error("增加敏感词-controller-addWord-异常:", e);
            return BaseResultUtils.generateFail("添加敏感词失败");
        }

    }

    /**
     * 导入敏感词
     *
     * @param file
     * @return
     */
    @RequestMapping(value = "/import", method = RequestMethod.POST)
    public BaseResult<Boolean> importWords(@RequestBody MultipartFile file) {
        try {
            InputStream inputStream = file.getInputStream();
            ExcelReader reader = ExcelUtil.getReader(inputStream);
            List<List<Object>> list = reader.read(1);
            int total = 0;
            for (int i = 0; i < list.size(); i++) {
                List<Object> rows = list.get(i);
                SensitiveWordDto sensitiveWordDto = new SensitiveWordDto();
                sensitiveWordDto.setWord(rows.get(0).toString());
                sensitiveWordDto.setCategory(rows.get(1).toString());
                // todo 后续可以优化为批量插入
                int count = sensitiveService.insert(sensitiveWordDto);
                total += count;

            }
            log.info("批量导入敏感词-controller层-importWords-插入敏感词数量:{}", total);
            return BaseResultUtils.generateSuccess(total > 0);
        } catch (IOException e) {
            log.error("批量导入敏感词-controller层-importWords-异常:", e);
            return BaseResultUtils.generateFail("导入失败，请联系相关开发人员");
        }

    }

    /**
     * 导出敏感词
     * 这样写会导致 读入大量对象 且JVM里面writer.write造成大量内存使用
     *
     * @param response
     * @return
     */
    @Deprecated
    @RequestMapping(value = "/exportOld", method = RequestMethod.GET)
    public BaseResult<Boolean> exportOldWords(HttpServletResponse response) {
        try {
            TbSensitiveWordsExample example = new TbSensitiveWordsExample();
            example.setLimit(1000);
            // 查询数据
            // todo 不能一次查询全部，要分页查询
            List<SensitiveWordDto> sensitiveWordDtos = sensitiveService.queryByParam(example);

            ExcelWriter writer = ExcelUtil.getWriter();
            writer.write(sensitiveWordDtos, true);
            // todo 导出的表头显示中文
            response.setContentType("application/vnd.ms-excel;charset=utf-8");
            // todo 文件名称增加区分性
            response.setHeader("Content-Disposition", "attachment;filename=sensitiveWords.xlsx");

            ServletOutputStream outputStream = response.getOutputStream();
            writer.flush(outputStream, true);
            writer.close();

            return BaseResultUtils.generateSuccess(true);
        } catch (Exception e) {
            log.error("批量导出敏感词-controller层-exportWords:", e);
            return BaseResultUtils.generateFail("导出敏感词异常，请联系相关开发人员");
        }
    }

    /**
     * 导出敏感词
     *
     * @param response
     * @return
     */
    @RequestMapping(value = "/export", method = RequestMethod.GET)
    public void exportWords(@RequestParam(value = "category", required = false) String category, HttpServletResponse response) {
        try {
            TbSensitiveWordsExample example = new TbSensitiveWordsExample();
            TbSensitiveWordsExample.Criteria criteria = example.createCriteria();
            if (StringUtils.isNotBlank(category)) {
                criteria.andCategoryEqualTo(category);
            }
            example.setLimit(EXPORT_NUM_LIMIT);
            // 查询
            List<SensitiveWordDto> sensitiveWordDtos = sensitiveService.queryByParam(example);

            List<ExportSensitiveWordDto> exportSensitiveWordDtos = buildExportSensitiveWordDtos(sensitiveWordDtos);

            response.setContentType("application/vnd.ms-excel");
            response.setCharacterEncoding(StandardCharsets.UTF_8.name());
            // 文件名
            String fileName = URLEncoder.encode("导出敏感词-" + DateUtils.getCurrentTimeStr() + EXCEL_SUFFIX, StandardCharsets.UTF_8.name());
            response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
            // 把内容填充到输出流
            EasyExcel.write(response.getOutputStream(), ExportSensitiveWordDto.class).sheet("cjk敏感词").doWrite(exportSensitiveWordDtos);
        } catch (Exception e) {
            log.error("批量导出敏感词-controller层-exportWords:", e);
        }
    }

    private List<ExportSensitiveWordDto> buildExportSensitiveWordDtos(List<SensitiveWordDto> sensitiveWordDtos) {
        if (CollectionUtils.isEmpty(sensitiveWordDtos)) {
            return new ArrayList<>();
        }
//        List<ExportSensitiveWordDto> targetList = new ArrayList<>();
//        for (int i = 0; i < sensitiveWordDtos.size(); i++) {
//            SensitiveWordDto source = sensitiveWordDtos.get(i);
//            ExportSensitiveWordDto target = new ExportSensitiveWordDto();
//            BeanUtils.copyProperties(source, target);
//            targetList.add(target);
//        }
        List<ExportSensitiveWordDto> targetList = sensitiveWordDtos.stream().map(item -> {
            ExportSensitiveWordDto exportSensitiveWordDto = new ExportSensitiveWordDto();
            BeanUtils.copyProperties(item, exportSensitiveWordDto);
            return exportSensitiveWordDto;
        }).collect(Collectors.toList());
        return targetList;
    }

    /**
     * 参数校验
     *
     * @param param
     */
    private void checkParam(AddSensitiveWordParam param) {
        Assert.isTrue(param != null, "入参不允许为空");
        Assert.isTrue(StringUtils.isNoneBlank(param.getWord()), "敏感词不允许为空");
        Assert.isTrue(StringUtils.isNoneBlank(param.getCategory()), "类别不允许为空");
    }
}
